package cn.okcode.slowjson;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import org.apache.commons.lang.StringUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ExcelUtils {
    public static <T> Sheet<T> read(Class<T> clazz, String fileName, int sheetNo) {
        return read(clazz, new File(fileName), sheetNo);
    }

    public static <T> Sheet<T> read(Class<T> clazz, String fileName, String sheetName) {
        return read(clazz, new File(fileName), sheetName);
    }

    public static <T> Sheet<T> read(Class<T> clazz, File file, int sheetNo) {
        ReadSheet readSheet = EasyExcel.readSheet(sheetNo).build();
        return read(clazz, file, readSheet);
    }

    public static <T> Sheet<T> read(Class<T> clazz, File file, String sheetName) {
        ReadSheet readSheet = EasyExcel.readSheet(sheetName).build();
        return read(clazz, file, readSheet);
    }

    private static <T> Sheet<T> read(Class<T> clazz, File file, ReadSheet readSheet) {
        ExcelReader excelReader = null;
        Sheet<T> sheet = new Sheet<T>();
        try {
//            Consumer<T> rowWriter = sheet.results::add;
            if (clazz == Map.class) {

                excelReader = EasyExcel.read(file, new RowReadListener(sheet)).build();
            } else {
                excelReader = EasyExcel.read(file, clazz,
                        new RowReadListener(sheet)).build();
            }
            excelReader.read(readSheet);
        } finally {
            if (excelReader != null) {
                // 这里千万别忘记关闭，读的时候会创建临时文件，到时磁盘会崩的
                excelReader.finish();
            }
        }
        return sheet;
    }

    public static <T> List<Sheet<T>> readBetween(Class<T> clazz, String fileName, int sheetBeginNo, int sheetEndNo) {
        List<Sheet<T>> sheets = new ArrayList<>();
        for (int i = sheetBeginNo; i <= sheetEndNo; i++) {
            Sheet<T> sheet = read(clazz, fileName, i);
            if (StringUtils.isBlank(sheet.getSheetName())) {
                break;
            }
            sheets.add(sheet);
        }
        return sheets;
    }

    public static <T> List<Sheet<T>> readByCount(Class<T> clazz, String fileName, int count) {
        return readBetween(clazz, fileName, 0, count - 1);
    }

    public static String removeEndEmpty(String value) {
        if (value == null) return null;
        value = StringUtils.removeEnd(value, new String(new char[]{160}));
        value = StringUtils.removeEnd(value, new String(new char[]{32}));
        return value;
    }

    public static String removeAllEmpty(String value) {
        if (value == null) return null;
        value = StringUtils.replace(value, new String(new char[]{160}), "");
        value = StringUtils.replace(value, new String(new char[]{32}), "");
        return value;
    }

    private static class RowReadListener<T> extends AnalysisEventListener<T> {
        private Sheet<T> sheet;

        public RowReadListener(Sheet<T> sheet) {
            this.sheet = sheet;
        }

        @Override
        public void invoke(T data, AnalysisContext context) {
            sheet.rows.add(data);
        }

        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            sheet.sheetName = analysisContext.readSheetHolder().getSheetName();
        }
    }

    public static class Sheet<T> {
        private String sheetName;
        private List<T> rows = new ArrayList<>();

        public String getSheetName() {
            return sheetName;
        }

        public void setSheetName(String sheetName) {
            this.sheetName = sheetName;
        }

        public List<T> getRows() {
            return rows;
        }

        public void setRows(List<T> rows) {
            this.rows = rows;
        }
    }
}
